package com.moore.attendance.udp;

import android.os.Handler;
import android.os.Message;

import com.moore.attendance.MainActivity;
import com.moore.attendance.base.Command;
import com.moore.attendance.base.MyApplication;
import com.moore.attendance.uitls.Logs;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * Created by binbin on 2017/3/8.
 */

public class ConnectManager {
    private final String TAG = "ConnectManager";
    private static DatagramSocket mSocket;
    private static ConnectManager sInstance;
    private int sendNum = 0;
    private int registerNum = 0;

    private SendThread mSendThread;
    private ReceiveThread mReceiveThread;

    private ConnectManager() {
    }

    public static ConnectManager getInstance() {
        if (sInstance == null) {
            synchronized (ConnectManager.class) {
                if (sInstance == null) {
                    sInstance = new ConnectManager();
                }
            }
        }
        return sInstance;
    }

    public void connect() {
        if (mSocket == null || mSocket.isClosed()) {
            try {
                //获取连接
                mSocket = new DatagramSocket();
                Logs.e("Manager", "connect");
                mReceiveThread = new ReceiveThread();
                mReceiveThread.start();

                UdpHandler.getInstance().setIsReConnect(false);
                Message msg = new Message();
                msg.obj = "1001";
                msg.what = UdpHandler.MSG_SEND;
                UdpHandler.getInstance().sendMessage(msg);
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    }

    public void disConnect() {
        if (mSocket != null && !mSocket.isClosed()) {
            if (mReceiveThread != null && !mReceiveThread.isInterrupted()) {
                mReceiveThread.interrupt();
            }
            if (mSendThread != null && !mSendThread.isInterrupted()) {
                mSendThread.interrupt();
            }
            mSocket.close();
//            mSocket = null;
        }
        //退出程序
        if (MyApplication.getInstance().getMain() != null) {
            Logs.e("CrashHandler", "finishService");
            MainActivity activity = (MainActivity) MyApplication.getInstance().getMain();
            activity.finishService();
        }
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    public void sendPackageRegister() {
        // TODO: 2017/9/3 离线，不要心跳包
//        if (registerNum > 2) {
//            Logs.e("ConnectionManager", "三次没收到1002回复，重新注册连接");
//            registerNum = 0;
//            UdpHandler.getInstance().setIsRecieveRegister(false);
//            UdpHandler.getInstance().setIsReConnect(true);
//            ConnectManager.this.disConnect();
//            ConnectManager.this.connect();
//            return;
//        }
        String content = "(1001," + Command.deviceId + ",register)";
        restartSend(content);
    }

    public void sendPackagePing() {
//        if (sendNum > 2) {
//            Logs.e("ConnectionManager", "三次没收到1002回复，重新注册连接");
//            sendNum = 0;
//            UdpHandler.getInstance().setIsRecieveRegister(false);
//            UdpHandler.getInstance().setIsReConnect(true);
//            ConnectManager.this.disConnect();
//            ConnectManager.this.connect();
//            return;
//        }
        String content = "(1002," + Command.deviceId + ",heartbeat)";
        restartSend(content);
    }

    public void sendPackageOk(String cardNo) {
        String content = "(1003," + Command.deviceId + "," + cardNo + ",ok)";
        restartSend(content);
    }

    public void sendPackageDownload(String url) {
        String content = "(1005," + Command.deviceId + "," + url + ",ok)";
        restartSend(content);
    }

    public void sendPackageDownloadSuccess(String url) {
        String content = "(1006," + Command.deviceId + "," + url + ",ok)";
        restartSend(content);
    }

    private void sendPackagePowerOnAtTime(String time){
        String content = "("+UdpKind.POWNER_ON_AT_TIME+","+Command.deviceId+","+time+",ok)";
        restartSend(content);
    }

    private void sendPackageCancelPowerOnAtTime(){
        String content = "("+UdpKind.CANCEL_POWNER_ON_AT_TIME+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void sendPackagePowerOffAtTime(String time){
        String content = "("+UdpKind.POWNER_OFF_AT_TIME+","+Command.deviceId+","+time+",ok)";
        restartSend(content);
    }

    private void sendPackageCancelPowerOffAtTime(){
        String content = "("+UdpKind.CANCEL_POWNER_OFF_AT_TIME+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void sendPackageShutDown(){
        String content = "("+UdpKind.SHUT_DOWN+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void sendPackageRestart(){
        String content = "("+UdpKind.RESTART+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void sendPackageOpenScreen(){
        String content = "("+UdpKind.OPEN_SCREEN+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void sendPackageCloseScreen(){
        String content = "("+UdpKind.CLOSE_SCREEN+","+Command.deviceId+",ok)";
        restartSend(content);
    }

    private void restartSend(String content) {
        if (mSendThread != null && !mSendThread.isInterrupted()) {
            mSendThread.interrupt();
        }
        mSendThread = null;
        mSendThread = new SendThread(content);
        mSendThread.start();
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 2) {
                mReceiveThread.interrupt();
                mReceiveThread = null;
                mReceiveThread = new ReceiveThread();
                mReceiveThread.start();
            }
        }
    };

    public class SendThread extends Thread {
        DatagramPacket packet;

        public SendThread(String content) {
            byte[] datas = content.getBytes();
            if (content.contains("register")) {
                registerNum++;
            }
            if (content.contains("heartbeat")) {
                sendNum++;
            }
            InetAddress address = null;
            try {
                address = InetAddress.getByName(Command.udp_address);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            if (address != null)
                packet = new DatagramPacket(datas, datas.length, address, Command.udp_port);
            else {
                //解析地址失败，强行给本机发送udp包
                try {
                    packet = new DatagramPacket(datas, datas.length, InetAddress.getByName("127.0.0.1"), Command.udp_port);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (listener != null)
                    listener.toastInfo("解析UDP通信地址失败！");
            }
        }

        @Override
        public void run() {
            super.run();
            try {
                if (mSocket == null || mSocket.isClosed())
                    return;
                if (packet != null && packet.getAddress() != null) {
                    mSocket.send(packet);
                    Logs.e("ConnectManager", "send success data is:" + new String(packet.getData()));
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 接收udp信息线程
     */
    private class ReceiveThread extends Thread {
        @Override
        public void run() {
            super.run();
            if (mSocket == null || mSocket.isClosed())
                return;
            try {
                byte datas[] = new byte[512];
                InetAddress address = InetAddress.getByName(Command.udp_address);
                DatagramPacket packet = new DatagramPacket(datas, datas.length, address, Command.udp_port);
                mSocket.receive(packet);
                String receiveMsg = new String(packet.getData()).trim();
                handleReceivePackage(receiveMsg);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 处理接收到的udp信息
     *
     * @param receiveMsg
     */
    private void handleReceivePackage(String receiveMsg) {
        //回调在首页显示
        if (listener != null) {
            listener.sendUdpInfo(receiveMsg);
        }
        Logs.e("ConnectManager", "receive msg data is:" + receiveMsg);
        UdpPackage receivePackage = ParseUdpUtil.getPackage(receiveMsg);
        if (receivePackage == null)
            return;
        Logs.e("ConnectManager", "package:" + receivePackage.toString());
        String packageNum = receivePackage.getPackageNum();
        if (packageNum == null)
            return;
        /**
         * 注册成功，发送心跳包
         * 注册计数清零
         */
        if (UdpKind.REGISTER.equals(packageNum)) {
            Message msg = new Message();
            msg.what = UdpHandler.MSG_SEND;
            UdpHandler.getInstance().setIsRecieveRegister(true);
            msg.obj = "1002";
            UdpHandler.getInstance().sendMessage(msg);
            registerNum = 0;
        }
        /**
         * 收到心跳包，计数清零
         */
        if (UdpKind.HEARTBEAT.equals(packageNum)) {
            sendNum = 0;
        }
        /**
         * 收到拍照指令
         */
        if (UdpKind.TAKE_PHOTO.equals(packageNum)) {
            if (Command.isTakePhoto) {
                Logs.e(TAG, "正在拍照，不能开启摄像头！");
                return;
            }
            Command.isTakePhoto = true;
            sendPackageOk(receivePackage.getOtherInfo());
            if (listener != null) {
                listener.openCamera(receivePackage.getOtherInfo());
            }
        }
        /**
         * 下载视频指令
         */
        if (UdpKind.DOWNLOAD_VIDEO.equals(packageNum)) {
            sendPackageDownload(receivePackage.getOtherInfo());
            if (listener != null) {
                listener.downloadVideo(receivePackage.getOtherInfo());
            }
        }
        /**
         * 定时开机
         */
        if (UdpKind.POWNER_ON_AT_TIME.equals(packageNum)) {
            sendPackagePowerOnAtTime(receivePackage.getOtherInfo());
            if (listener != null) {
                listener.powerOnAtTime(receivePackage.getOtherInfo());
            }
        }
        /**
         * 取消定时开机
         */
        if (UdpKind.CANCEL_POWNER_ON_AT_TIME.equals(packageNum)) {
            sendPackageCancelPowerOnAtTime();
            if (listener != null) {
                listener.cancelPowerOn();
            }
        }
        /**
         * 定时关机
         */
        if (UdpKind.POWNER_OFF_AT_TIME.equals(packageNum)) {
            sendPackagePowerOffAtTime(receivePackage.getOtherInfo());
            if (listener != null)
                listener.powerOffAtTime(receivePackage.getOtherInfo());
        }
        /**
         * 取消定时关机
         */
        if (UdpKind.CANCEL_POWNER_OFF_AT_TIME.equals(packageNum)) {
            sendPackageCancelPowerOffAtTime();
            if (listener != null)
                listener.cancelPowerOff();
        }
        /**
         * 关机
         */
        if (UdpKind.SHUT_DOWN.equals(packageNum)) {
            sendPackageShutDown();
            if (listener != null)
                listener.shutDown();
        }
        /**
         * 重启
         */
        if (UdpKind.RESTART.equals(packageNum)) {
            sendPackageRestart();
            if (listener != null)
                listener.restart();
        }
        /**
         * 开启屏幕
         */
        if (UdpKind.OPEN_SCREEN.equals(packageNum)) {
            sendPackageOpenScreen();
            if (listener != null)
                listener.openScreen();
        }
        /**
         * 关闭屏幕
         */
        if (UdpKind.CLOSE_SCREEN.equals(packageNum)) {
            sendPackageCloseScreen();
            if (listener != null)
                listener.closeScreen();
        }
        mHandler.sendEmptyMessage(2);
    }

    private UdpSocketListener listener;

    public void setOnOpenCameraListener(UdpSocketListener listener) {
        this.listener = listener;
    }

    public interface UdpSocketListener {
        void openCamera(String cardNo);

        void sendUdpInfo(String udpInfo);

        void downloadVideo(String videoInfo);

        void toastInfo(String info);

        void powerOnAtTime(String time);

        void cancelPowerOn();

        void powerOffAtTime(String time);

        void cancelPowerOff();

        void shutDown();

        void restart();

        void openScreen();

        void closeScreen();
    }

}
